/* Mercury noun space replica browser
 * Copyright 2008 Cary Hull
 *
 * Ripped from jQuery Impromptu and heavily modded/specialized.
 * Copyright 2008 Trent Richardson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
jQuery.extend({	
  MercuryDefaults: {
    prefix: 'merc',
    opacity: 0.7,
    zIndex: 999,
    overlayspeed: 'slow',
    },

  SetMercuryDefaults: function(o) {jQuery.MercuryDefaults = jQuery.extend({}, jQuery.MercuryDefaults, o);},

  mercury_prompt: function(send_filter_changed, opts) {
    opts = jQuery.extend({}, jQuery.MercuryDefaults, opts);
    var jbody = jQuery(document.body);
    var jwin = jQuery(window);
              
    var box_id = opts.prefix + 'Box';
    // See if box_id is already present in dom, if so we just return.
    var existing_box = jbody.find('#' + box_id);
    if (existing_box.length) {
      console.log('Mercury already loaded, doing nothing...');
      return;
      }

    var esc_key = 'Esc';
    var enter_key = 'Enter';

    // Build and insert core DOM elements that make up the Mercury UI
    var box = $('<div/>')
        .attr('class', box_id)
        .attr('id', box_id)
        .appendTo(jbody);

    var fade_id = opts.prefix + 'Fade';
    var fade = $('<div/>')
        .attr('class', fade_id)
        .attr('id', fade_id)
        .appendTo(box);

    var dialog = $('<div/>')
        .attr('class', opts.prefix)
        .attr('id', opts.prefix)
        .appendTo(box);

    $('<span/>')
        .attr('class', 'mercury_title')
        .html('mercury')
        .appendTo(dialog);

    var closer = $('<button/>')
        .html(esc_key)
        .css({'position': 'absolute', 'left': '95%', 'margin': '10px'})
        .appendTo(dialog);

    var filter_inputs = $('<fieldset/>')
        .attr('class', 'mercury_filters')
        .appendTo(dialog);

    var no_results_hint = 'Not seeing results? Ctrl+e will sync new events to the local store.';
    $('<span/>')
        .html(no_results_hint) 
        .css({'position': 'absolute', 'left': '50%', 'margin': '10px'})
        .appendTo(dialog);

    var filter_inputs_list = $('<ol/>').appendTo(filter_inputs);

    var mprefix = 'mercury_';
    var addFilterInput = function(filter_name) {
      var filter_id = mprefix + filter_name;
      var wrapper = $('<li/>')
          .attr('class', 'mercury_input')
          .appendTo(filter_inputs_list);
      $('<label/>')
          .attr('for', filter_id)
          .html(filter_name)
          .appendTo(wrapper);
      $('<input/>')
          .attr('id', filter_id)
          .appendTo(wrapper);
      };

    addFilterInput('root');
    addFilterInput('types');
    addFilterInput('authors');
    addFilterInput('keywords');

    var input_fields = filter_inputs.find(':input');
    // input_fields.get(0).focus();

    $('<div/>')
        .attr('class', 'clearerer')
        .appendTo(dialog);

    var results_id = opts.prefix + 'Results';
    var results = $('<div/>')
        .attr('class', results_id)
        .attr('id', results_id)
        .appendTo(box);


    var filterChanged = function(ev) {
      // Derive new query result and render
      console.log('input changed', ev.target);
      var params = {};
      var count = 0;
      for (var i=0; i<input_fields.length; i++) {
        var inp = input_fields.get(i);
        var param_name = inp.id.slice(mprefix.length);
        console.log('input field:', i, inp, param_name, inp.value);
        var value = $.trim(inp.value);
        if (value) {
          params[param_name] = value;
          count += 1;
          } 
        }

      if (count) {
        send_filter_changed(params);
        }
      else {
        results.empty()
        }
      };

    dialog.intercept('change', 'input', filterChanged);
    $(document).bind('keydown', enter_key, filterChanged);

    var resultClicked = function(ev) {
      var span = ev.target;
      console.log('span got clicked', span, span.id);
      $('span.selected').toggleClass('selected');
      $(span).toggleClass('selected');
      };

    results.intercept('click', 'span', resultClicked);


    var resultDblClicked = function(ev) {
      // Take them where they want to go
      var span = ev.target;
      console.log('span got dbl clicked', span, span.id);
      $('span.selected').toggleClass('selected');
      $(span).toggleClass('selected');
      location.href = location.protocol + '//' + location.host + span.id;
      };

    results.intercept('dblclick', 'span', resultDblClicked);


    var flashPrompt = function() {
      var i = 0;
      var warning_classname = opts.prefix + 'Warning';
      box.addClass(warning_classname);
      var interval_id = setInterval(function() {
          box.toggleClass(warning_classname);
          if(i++ > 1) {
            clearInterval(interval_id);
            box.removeClass(warning_classname);
            }
          }, 100);
      };


    var positionElements = function() {
      var window_height = $(document).height();
      box.css({position: 'fixed', height: window_height, width: '100%', top: 0, left: 0, right: 0, bottom: 0});
      fade.css({position: 'absolute', height: window_height, width: '100%', top: 0, left: 0, right: 0, bottom: 0});
      dialog.css({
          position: 'absolute',
          top: '0px',
          left: '0px',
          width: '100%',
          });
      results.css({
          position: 'absolute',
          top: dialog.height() + 'px',
          left: '0px',
          width: '100%',
          });
      };
            

    var styleElements = function() {
      fade.css({zIndex: opts.zIndex, display: 'none', opacity: opts.opacity});
      dialog.css({zIndex: opts.zIndex + 1, display: 'none'});
      results.css({zIndex: opts.zIndex + 1, display: 'none'});
      };


    var removeElements = function(){
      results.remove();
      dialog.slideUp('fast', function() {dialog.remove()}); 
      jwin.unbind('resize', positionElements);
      fade.fadeOut(opts.overlayspeed, function() {
          fade.unbind('click', flashPrompt);
          fade.remove();
          $(document).unbind('keydown', esc_key, removeElements);
          $(document).unbind('keydown', enter_key, filterChanged);
          box.remove();
          });
      };


    positionElements();
    styleElements();

    fade.click(flashPrompt);
    jwin.resize(positionElements);
    $(document).bind('keydown', esc_key, removeElements);
    closer.click(removeElements);

    //Show it
    fade.fadeIn(opts.overlayspeed);
    dialog.slideDown('fast')
    results.show();
    return box;
    }
});
